<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <style>
      body{
    margin: 0;
    font-size: 14px;
}
    </style>
</head>

<body>
   <div id="jsContainer">
    <ul class="js-test" id="jsParent">
        <li data-index="0">1</li>
        <li data-index="1">2</li>
    </ul>
    <span style="font-weight: bold;">3</span>
    4
</div>
    <script type="text/javascript">
/*
页面上存在 id = jsContainer 的节点A， 系统会随机在节点A中生成文档片段，按如下需求实现dom2json函数
1. dom2json 需要分析整个节点A的dom结构，并将其结构转换为对应的json对象
2. 需要获取dom结构的标签名称(tag), 所有属性(attributes) 子节点(children)
3. 文档片段中的属性形式 均为 name = "value", 解析之后的格式为{name:value} 属性值为String类型，不需要做解析
4. 随机生成的文档片段中，只包含nodeType为1 (element) 和 3(texxt)的节点，不需要考虑其他节点类型
5. 纯文本也是为一个节点，json格式为 {tag: 'text', content: '文本内容'}, content为文本内容执行trim后的结果，如果该结果为空，则忽略当前节点
6. 返回结果中的标签名称不区分大小写
 */
function dom2json() {
    const jsContainer = document.getElementById('jsContainer');
    return createObj(jsContainer);
}
// 递归遍历dom树取各节点元素属性转json
function createObj(element) {
    // 0. 创建一个空的对象
    const obj = {};
    // 1. 获得标签名，nodeName可以获得text标签(里面好多回车)，typeName获得是标签
    obj.tag = element.nodeName.toLowerCase().replace('#', '');
    // 2.如果是文本，有content属性，通过element.data来获得内容
    if (obj.tag == 'text') {
        obj.content = element.data.trim();
    }
    // 3.attributes初始化，如果有，那么逐个添加attributes
    obj.attributes = {};
    if (element.attributes) {
        for (let i = 0; i < element.attributes.length; i++) {
            const { name, value } = element.attributes[i];
            obj.attributes[name] = value;
        }
    }
    // 4.0对孩子数组过滤，去除没有内容的text
    const childArr = Array.from(element.childNodes).filter((item) => {
        return item.nodeName === '#text' && item.data.trim() !== '' || item.nodeName !== '#text';
    });
    // 4.1如果有孩子，那么递归调用自己，添加第i个数组元素
    obj.children = [];
    if (childArr.length) {
        for (let i = 0; i < childArr.length; i++) {
            obj.children[i] = createObj(childArr[i]);
        }
    }
    return obj;
}
    </script>
</body>

</html>